﻿namespace Baddies.Nodes
{
    using System;
    using System.Collections.Generic;
    using System.Diagnostics;
    using System.Linq;
    using System.Text;
    using Microsoft.Xna.Framework.Graphics;    

    /// <summary>
    /// Node that acts as a Finite State Machine for it's children,
    /// ensuring only one is active (update and drawn) at any given 
    /// time.
    /// </summary>
    public class FSMNode : Node
    {
        /// <summary>
        /// Active node of the FSM.
        /// </summary>
        private Node activeNode = null;

        /// <summary>
        /// Gets the activeNode.
        /// </summary>
        /// <value>The current activeNode.</value>
        public Node ActiveNode
        {
            get { return this.activeNode; }
        }

        /// <summary>
        /// Updates the active node only.
        /// </summary>
        public override void NodeUpdate()
        {
            this.Update();

            if (this.activeNode != null)
            {
                this.activeNode.NodeUpdate();
            }
        }

        /// <summary>
        /// Draws the activeNode.
        /// </summary>
        /// <param name="spritebatch">Spritebatch to draw on.</param>
        public override void NodeDraw(SpriteBatch spritebatch)
        {
            if (!this.Visible)
            {
                return;
            }

            this.Draw(spritebatch);
            if (this.activeNode != null)
            {
                this.activeNode.NodeDraw(spritebatch);
            }
        }

        /// <summary>
        /// Changes the current node for another of the children of the node.
        /// When changing the node, we call End on the old node and Enter on the new one.
        /// </summary>
        /// <param name="tag">Tag referencing the new child we want as active node.</param>
        public void ChangeActiveNode(int tag)
        {
            // Check the tag exists
            Debug.Assert(this.Contains(tag), "No children matching that tag!");

            // Check the new node isn't null
            Node newActiveNode = this.Children[tag];
            Debug.Assert(newActiveNode != null, "Child to set as new active node was null!");

            // Change active node
            if (this.activeNode != null)
            {
                this.activeNode.End();
            }

            this.activeNode = newActiveNode;

            this.activeNode.Enter();
        }
    }
}
